/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.myfaces.el;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.el.ReferenceSyntaxException;
import javax.faces.el.VariableResolver;
import javax.faces.FacesException;
import org.apache.myfaces.config.ManagedBeanBuilder;
import org.apache.myfaces.config.RuntimeConfig;
import org.apache.myfaces.config.element.ManagedBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Manfred Geiler (latest modification by $Author$)
* @author Anton Koinov
* @version $Revision$ $Date$
*/
public class VariableResolverImpl
extends VariableResolver
{
//~ Static fields/initializers -----------------------------------------------------------------
private static final Log log = LogFactory.getLog(VariableResolverImpl.class);
private static final String BEANS_UNDER_CONSTRUCTION = "org.apache.myfaces.config.beansUnderConstruction";
//~ Instance fields ----------------------------------------------------------------------------
public static final Map s_standardImplicitObjects = new HashMap(32);
static {
s_standardImplicitObjects.put(
"applicationScope",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getApplicationMap();
}
});
s_standardImplicitObjects.put(
"cookie",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestCookieMap();
}
});
s_standardImplicitObjects.put(
"facesContext",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext;
}
});
s_standardImplicitObjects.put(
"header",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestHeaderMap();
}
});
s_standardImplicitObjects.put(
"headerValues",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestHeaderValuesMap();
}
});
s_standardImplicitObjects.put(
"initParam",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getInitParameterMap();
}
});
s_standardImplicitObjects.put(
"param",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestParameterMap();
}
});
s_standardImplicitObjects.put(
"paramValues",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestParameterValuesMap();
}
});
s_standardImplicitObjects.put(
"requestScope",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getRequestMap();
}
});
s_standardImplicitObjects.put(
"sessionScope",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getExternalContext().getSessionMap();
}
});
s_standardImplicitObjects.put(
"view",
new ImplicitObject()
{
public Object get(FacesContext facesContext)
{
return facesContext.getViewRoot();
}
});
}
/**
* Stores all implicit objects defined for this instance of <code>VariableResolver</code>
* <p>
* Can store instances of <code>ImplicitObject</code> which have the ability to
* dynamically resolve against FacesContext. Can also store any other object
* which itself is the value for the implicit object (this in effect will be
* a static object).
* </p>
* <p>
* WARNING: this implementation is not serialized as it is thread safe because
* it does not update/add to _implicitObjects after object initialization.
* If you need to add your own implicit objects, either extend and add more
* in an initialization block, or add proper sychronization
* </p>
*/
protected final Map _implicitObjects = new HashMap(32);
{
_implicitObjects.putAll(s_standardImplicitObjects);
}
protected static final Map s_standardScopes = new HashMap(16);
static {
s_standardScopes.put(
"request",
new Scope()
{
public void put(ExternalContext extContext, String name, Object obj)
{
extContext.getRequestMap().put(name, obj);
}
});
s_standardScopes.put(
"session",
new Scope()
{
public void put(ExternalContext extContext, String name, Object obj)
{
extContext.getSessionMap().put(name, obj);
}
});
s_standardScopes.put(
"application",
new Scope()
{
public void put(ExternalContext extContext, String name, Object obj)
{
extContext.getApplicationMap().put(name, obj);
}
});
s_standardScopes.put(
"none",
new Scope()
{
public void put(ExternalContext extContext, String name, Object obj)
{
// do nothing
}
});
}
/**
* Stores all scopes defined for this instance of <code>VariableResolver</code>
* <p>
* Can store instances of <code>Scope</code> which have the ability to
* dynamically resolve against ExternalContext for put operations.
* </p>
* <p>
* WARNING: this implementation is not serialized as it is thread safe because
* it does not update/add to _scopes after object initialization.
* If you need to add your own scopes, either extend and add more
* in an initialization block, or add proper sychronization
* </p>
*/
protected final Map _scopes = new HashMap(16);
{
_scopes.putAll(s_standardScopes);
}
/**
* RuntimeConfig is instantiated once per servlet and never changes--we can
* safely cache it
*/
private RuntimeConfig _runtimeConfig;
private ManagedBeanBuilder beanBuilder = new ManagedBeanBuilder();
//~ Methods ---------------------------------------------------------------
public Object resolveVariable(FacesContext facesContext, String name)
{
if ((name == null) || (name.length() == 0))
{
throw new ReferenceSyntaxException("Varible name is null or empty");
}
// Implicit objects
Object implicitObject = _implicitObjects.get(name);
if (implicitObject != null)
{
if (implicitObject instanceof ImplicitObject)
{
// a complex runtime object
return ((ImplicitObject) implicitObject).get(facesContext);
}
else
{
// a simple object
return implicitObject;
}
}
ExternalContext externalContext = facesContext.getExternalContext();
// Request context
Map requestMap = externalContext.getRequestMap();
Object obj = requestMap.get(name);
if (obj != null)
{
return obj;
}
// Session context
obj = externalContext.getSessionMap().get(name);
if (obj != null)
{
return obj;
}
// Application context
obj = externalContext.getApplicationMap().get(name);
if (obj != null)
{
return obj;
}
// ManagedBean
ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(name);
if (mbc != null)
{
// check for cyclic references
List beansUnderConstruction = (List)requestMap.get(BEANS_UNDER_CONSTRUCTION);
if (beansUnderConstruction == null) {
beansUnderConstruction = new ArrayList();
requestMap.put(BEANS_UNDER_CONSTRUCTION, beansUnderConstruction);
}
String managedBeanName = mbc.getManagedBeanName();
if (beansUnderConstruction.contains(managedBeanName)) {
throw new FacesException( "Detected cyclic reference to managedBean " + mbc.getManagedBeanName());
}
beansUnderConstruction.add(managedBeanName);
try {
obj = beanBuilder.buildManagedBean(facesContext, mbc);
} finally {
beansUnderConstruction.remove(managedBeanName);
}
// put in scope
String scopeKey = mbc.getManagedBeanScope();
// find the scope handler object
Scope scope = (Scope) _scopes.get(scopeKey);
if (scope == null)
{
log.error("Managed bean '" + name + "' has illegal scope: "
+ scopeKey);
}
else
{
scope.put(externalContext, name, obj);
}
if(obj==null && log.isDebugEnabled())
{
log.debug("Variable '" + name + "' could not be resolved.");
}
return obj;
}
if(log.isDebugEnabled())
{
log.debug("Variable '" + name + "' could not be resolved.");
}
return null;
}
protected RuntimeConfig getRuntimeConfig(FacesContext facesContext)
{
if (_runtimeConfig == null)
{
_runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
}
return _runtimeConfig;
}
}
interface ImplicitObject
{
//~ Methods ---------------------------------------------------------------
public Object get(FacesContext facesContext);
}
interface Scope
{
//~ Methods ---------------------------------------------------------------
public void put(ExternalContext extContext, String name, Object obj);
}